/**
 * 广寒宫
 * 网址:www.guanghangong.xyz
 */
package com.moon.admin.framework.mybatisplus.tenant;

import com.moon.admin.framework.mybatisplus.props.JdbcPoolProperties;
import com.moon.admin.framework.mybatisplus.props.JdbcProperties;
import com.moon.admin.framework.mybatisplus.tenant.domain.TenantDataSource;
import com.moon.admin.framework.springmvc.config.SpringContextConfig;
import com.moon.admin.framework.util.JsonUtils;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 动态数据源路由
 * @author moon
 */
public class DynamicMultipleDataSource extends AbstractRoutingDataSource{

    private static final ThreadLocal<String> dataSourceKey = ThreadLocal.withInitial(() -> "default");

    public static Map<Object, Object> dataSourcesMap = new ConcurrentHashMap<>(10);

    @Override
    protected Object determineCurrentLookupKey() {
        final String lookupKey =  dataSourceKey.get();
        dataSourceKey.remove();
        return lookupKey;
    }

    /**
     * 利用threadlocal临时切换数据源，在determineCurrentLookupKey中移除threadloca变量
     * @param dataSource
     */
    public static void setDataSource(String dataSource) {
        dataSourceKey.set(dataSource);
        DynamicMultipleDataSource dynamicDataSource = (DynamicMultipleDataSource) SpringContextConfig.getBean("dataSource");
        dynamicDataSource.afterPropertiesSet();
    }

    /**
     * 构建连接池
     * @param poolProperties
     * @return
     */
    public static HikariDataSource buildDataSource(JdbcPoolProperties poolProperties){
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setAutoCommit(poolProperties.isAutoCommit());
        hikariDataSource.setConnectionTimeout(poolProperties.getConnectionTimeout());
        hikariDataSource.setIdleTimeout(poolProperties.getIdleTimeout());
        hikariDataSource.setMaxLifetime(poolProperties.getMaxLifetime());
        hikariDataSource.setMaximumPoolSize(poolProperties.getMaximumPoolSize());
        hikariDataSource.setMinimumIdle(poolProperties.getMinimumIdle());
        hikariDataSource.setInitializationFailTimeout(poolProperties.getInitializationFailTimeout());
        hikariDataSource.setIsolateInternalQueries(poolProperties.isIsolateInternalQueries());
        hikariDataSource.setReadOnly(poolProperties.isReadOnly());
        hikariDataSource.setRegisterMbeans(poolProperties.isRegisterMbeans());
        Optional.ofNullable(poolProperties.getDriverClassName()).ifPresent(hikariDataSource::setDriverClassName);
        hikariDataSource.setValidationTimeout(poolProperties.getValidationTimeout());
        hikariDataSource.setLeakDetectionThreshold(poolProperties.getLeakDetectionThreshold());
        return hikariDataSource;
    }
}